package com.zhanghu.backendZray.job;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zhanghu.backendZray.enums.NotifyTypeEnum;
import com.zhanghu.backendZray.pojo.entity.DailyPlan;
import com.zhanghu.backendZray.pojo.entity.DailyTask;
import com.zhanghu.backendZray.pojo.entity.NotifySetting;
import com.zhanghu.backendZray.service.DailyPlanService;
import com.zhanghu.backendZray.service.DailyTaskService;
import com.zhanghu.backendZray.service.NotifySettingService;
import com.zhanghu.backendZray.strategy.notify.MailNotifyStrategy;
import com.zhanghu.backendZray.strategy.notify.NotifyFactory;
import com.zhanghu.backendZray.strategy.notify.NotifyStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import static java.util.stream.Collectors.*;

/**
 * 定时通知job
 * @author ZhangDong
 * @date 2024/8/28 22:02
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class NotifyJob {
    private final DailyPlanService dailyPlanService;
    private final DailyTaskService dailyTaskService;
    private final NotifySettingService notifySettingService;
    private final MailNotifyStrategy mailNotifyStrategy;

    private static final Map<Byte, NotifyStrategy> notifyMap = new HashMap<>(4);

    @PostConstruct
    public void initMap() {
        notifyMap.put(NotifyTypeEnum.MAIL.getType(), mailNotifyStrategy);
    }

    /**
     * 一分钟执行一次
     */
    @Scheduled(fixedRate = 1000 * 60, initialDelay = 5000)
    public void doNotify() {
        LambdaQueryWrapper<DailyTask> queryWrapper = new LambdaQueryWrapper<DailyTask>()
                .lt(DailyTask::getScheduledTaskDateTime, LocalDateTime.now())
                .eq(DailyTask::getStatus, 0);
        List<DailyTask> taskList = dailyTaskService.list(queryWrapper);
        if (CollUtil.isEmpty(taskList)) {
            return;
        }
        long start = System.currentTimeMillis();
        List<Long> taskIdList = taskList.stream().map(DailyTask::getId).collect(toList());
        log.info("通知任务, 开始执行.... taskIdList:{}", taskIdList);
        List<Long> planIdList = taskList.stream().map(DailyTask::getPlanId).distinct().collect(toList());
        LambdaQueryWrapper<DailyPlan> planLambdaQueryWrapper = new LambdaQueryWrapper<DailyPlan>().in(DailyPlan::getId, planIdList);
        Map<Long, DailyPlan> planMap = dailyPlanService.list(planLambdaQueryWrapper).stream().collect(toMap(DailyPlan::getId, Function.identity()));
        Map<Integer, NotifySetting> mailMap = notifySettingService.list().stream().collect(toMap(NotifySetting::getUserId, Function.identity()));
        for (DailyTask dailyTask : taskList) {
            Long planId = dailyTask.getPlanId();
            DailyPlan plan = planMap.get(planId);
            if (plan == null) {
                continue;
            }
            NotifySetting setting = mailMap.get(plan.getUserId());
            if (setting == null) {
                continue;
            }
            NotifyStrategy notifyStrategy = NotifyFactory.get(NotifyTypeEnum.getByType(setting.getType()));
            if (notifyStrategy == null) {
                log.info("通知任务，不支持此类型的通知, type:{}", setting.getType());
                continue;
            }
            boolean success = notifyStrategy.doNotify(plan, setting);
            if (success) {
                dailyTask.setStatus((byte) 1);
                dailyTaskService.updateById(dailyTask);
            }
        }
        log.info("通知任务, 结束执行.... taskIdList:{}, 耗时:{}ms", taskIdList, (System.currentTimeMillis() - start));
    }
}
